package com.franklin.ideaplugin.easytesting.ui.history;

import cn.hutool.core.collection.CollectionUtil;
import com.franklin.ideaplugin.api.ui.IBaseComponent;
import com.franklin.ideaplugin.api.utils.ProjectUtils;
import com.franklin.ideaplugin.api.utils.SwingUtils;
import com.franklin.ideaplugin.easytesting.cache.IEasyTestingCache;
import com.franklin.ideaplugin.easytesting.cache.impl.PersistenceEasyTestingCache;
import com.franklin.ideaplugin.easytesting.common.entity.ETRsp;
import com.franklin.ideaplugin.easytesting.configuration.UIConfigPersistentState;
import com.franklin.ideaplugin.easytesting.constant.ExecuteFormType;
//import com.franklin.ideaplugin.easytesting.editor.BaseScriptTextEditor;
import com.franklin.ideaplugin.easytesting.entity.ExecuteResult;
import com.franklin.ideaplugin.easytesting.icon.PluginIcons;
import com.franklin.ideaplugin.easytesting.notification.EasyTestingNotifier;
import com.franklin.ideaplugin.easytesting.ui.ExecuteMethodResultForm;
import com.franklin.ideaplugin.easytesting.ui.Sizes;
import com.franklin.ideaplugin.easytesting.ui.execute.ExecuteDubboForm;
import com.franklin.ideaplugin.easytesting.ui.execute.ExecuteMethodFormNew;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.FileEditor;
//import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
//import com.intellij.openapi.fileEditor.impl.EditorWindow;
//import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiInvalidElementAccessException;
import com.intellij.psi.PsiMethod;
import com.intellij.ui.tabs.JBTabs;

import javax.swing.*;
import java.awt.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author Ye Junhui
 * @since 2023/7/11
 */
public class ExecuteHistoryFormNew implements IBaseComponent {
    private JPanel mainPanel;
    private JPanel timePanel;
    private JPanel middlePanel;
    private JPanel rightPanel;
    private JPanel paramPanel;
    private JPanel resultPanel;
    private JSplitPane timePanelSplitPane;
    private JButton executeBtn;
    private JButton downloadBtn;
    private JButton rollbackExecuteBtn;
    private JButton threadPoolExecuteBtn;

    private JComponent parent;

    private IBaseComponent executeMethodFormNew;
    private ExecuteMethodResultForm executeMethodResultForm;

    private final PsiMethod psiMethod;
    private final Project project;

    private final ExecuteFormType executeFormType;

    public ExecuteHistoryFormNew(PsiMethod psiMethod, ExecuteFormType executeFormType) {
        this.psiMethod = psiMethod;
        this.project = psiMethod.getProject();
        this.executeFormType = executeFormType;
        this.initButton();
        UIConfigPersistentState uiConfigPersistentState = UIConfigPersistentState.getInstance();
        this.timePanelSplitPane.setDividerLocation(uiConfigPersistentState.historyWidth);
    }

    public void setParent(JComponent parent) {
        this.parent = parent;
    }

    public void init() {
        //参数面板
        IEasyTestingCache easyTestingCache = IEasyTestingCache.getInstance(ProjectUtils.getCurrProject());
        List<ExecuteResult> executeResultList = easyTestingCache.getExecuteResultList(psiMethod);
        if (CollectionUtil.isEmpty(executeResultList)) {
            this.refresh(null);
        } else {
            this.refresh(executeResultList.get(0));
        }
    }

    /**
     * 初始化按钮
     */
    private void initButton(){
        this.executeBtn = new JButton();
        this.executeBtn.setToolTipText("Execute Method");
        this.executeBtn.setIcon(AllIcons.Actions.Execute);
        this.executeBtn.setText("Execute Method");

        this.downloadBtn = new JButton();
        this.downloadBtn.setToolTipText("Execute Method And Download Result");
        this.downloadBtn.setIcon(AllIcons.Actions.Download);
        this.downloadBtn.setText("Execute Method And Download Result");

        this.rollbackExecuteBtn = new JButton();
        this.rollbackExecuteBtn.setToolTipText("Execute Method And Do Transaction Rollback");
        this.rollbackExecuteBtn.setIcon(AllIcons.General.RunWithCoverage);
        this.rollbackExecuteBtn.setText("Execute Method And Do Transaction Rollback");

        this.threadPoolExecuteBtn = new JButton();
        this.threadPoolExecuteBtn.setToolTipText("Pressure Test");
        this.threadPoolExecuteBtn.setIcon(PluginIcons.RUN_ICON);
        this.threadPoolExecuteBtn.setText("Pressure Test");
    }

    public JButton getExecuteBtn() {
        return executeBtn;
    }

    public JButton getRollbackExecuteBtn() {
        return rollbackExecuteBtn;
    }

    public JButton getDownloadBtn() {
        return downloadBtn;
    }

    public JButton getThreadPoolExecuteBtn() {
        return threadPoolExecuteBtn;
    }

    /**
     * 刷新面板
     *
     * @param executeResult
     */
    public void refresh(ExecuteResult executeResult) {
        try {
            this.refreshTimePanel(executeResult);
            this.refreshParamPanel(executeResult);
            this.refreshResultPanel(executeResult);
            this.refreshScriptPanel(executeResult);
            if (Objects.nonNull(this.parent)) {
                this.parent.validate();
            }
        } catch (PsiInvalidElementAccessException psiInvalidElementAccessException) {
            EasyTestingNotifier.notifyError(this.project, "当前方法所在类的虚拟文件已被GC，请重新打开表单窗口");
        }
    }

    public void refreshScriptPanel(ExecuteResult executeResult) {
        if (Objects.isNull(executeResult)){
            return;
        }

//        FileEditorManagerEx fileEditorManagerEx = FileEditorManagerEx.getInstanceEx(project);
//        EditorWindow currentWindow = fileEditorManagerEx.getCurrentWindow();
//        EditorWithProviderComposite selectedEditor = currentWindow.getSelectedEditor();
//        if (Objects.isNull(selectedEditor)){
//            return;
//        }
//        JBTabs tabs = selectedEditor.getTabs();
//        if (Objects.isNull(tabs)){
//            return;
//        }
//        ApplicationManager.getApplication().invokeLater(() -> {
//            EditorWithProviderComposite editorWithProviderComposite = currentWindow.getEditors()[0];
//            PersistenceEasyTestingCache easyTestingCache = (PersistenceEasyTestingCache) IEasyTestingCache.getInstance(psiMethod.getProject());
//            String code = easyTestingCache.flushScriptToExecuteFile(psiMethod, executeResult);
//            for (FileEditor editor : editorWithProviderComposite.getEditors()) {
//                if (editor instanceof BaseScriptTextEditor){
//                    BaseScriptTextEditor baseScriptTextEditor = (BaseScriptTextEditor) editor;
//                    baseScriptTextEditor.refreshText(code);
//                }
//            }
//
//        });
    }

    private void refreshTimePanel(ExecuteResult executeResult) {
        HistoryTree historyTree = new HistoryTree(psiMethod, this);
        this.timePanel.removeAll();
        this.timePanel.setLayout(SwingUtils.createLayoutManager(1, 1));
        this.addCell(this.timePanel, historyTree.getMainPanel(), 0, 0, Sizes.ExecuteHistoryFormSize.TIME_SIZE);
    }

    public void resize(Dimension parentSize) {
        int width = (int) ((parentSize.width - 250) / 2.0);
        Dimension dimension = new Dimension(width - 50, parentSize.height - 50);
        Dimension dimensionParam = new Dimension(width - 100, parentSize.height - 50);
        this.paramPanel.setSize(dimensionParam);
        if (Objects.nonNull(executeMethodFormNew)) {
            this.paramPanel.removeAll();
            executeMethodFormNew.getMainPanel().setSize(dimensionParam);
            this.addCell(this.paramPanel, executeMethodFormNew.getMainPanel(), 0, 0, dimensionParam);
        }
        this.resultPanel.setSize(dimension);
        if (Objects.nonNull(executeMethodResultForm)) {
            this.resultPanel.removeAll();
            executeMethodResultForm.getMainPanel().setSize(dimension);
            executeMethodResultForm.resize(dimension);
            this.addCell(this.resultPanel, executeMethodResultForm.getMainPanel(), 0, 0, dimension);
        }
    }

    /**
     * 刷新参数面板
     *
     * @param executeResult
     */
    private void refreshParamPanel(ExecuteResult executeResult) {
        Map<String, Object> paramMap = Collections.emptyMap();
        PersistenceEasyTestingCache easyTestingCache = (PersistenceEasyTestingCache) IEasyTestingCache.getInstance(psiMethod.getProject());
        String scriptPath = easyTestingCache.getExecuteScriptPath(psiMethod);
        ETRsp<?> lastRsp = null;
        if (Objects.nonNull(executeResult)) {
            paramMap = executeResult.getParamMap();
            lastRsp = executeResult.getEtRsp();
        }


        if (executeFormType == ExecuteFormType.NORMAL){
            executeMethodFormNew = new ExecuteMethodFormNew(
                    psiMethod,
                    paramMap,
                    this::refresh,
                    this.executeBtn,
                    this.downloadBtn,
                    this.rollbackExecuteBtn,
                    this.threadPoolExecuteBtn,
                    scriptPath,
                    lastRsp
            );
        }else {
            executeMethodFormNew = new ExecuteDubboForm(
                    psiMethod,
                    this.executeBtn,
                    paramMap,
                    this::refresh
            );
        }
        this.paramPanel.removeAll();
        this.paramPanel.setLayout(SwingUtils.createLayoutManager(1, 1));
        this.addCell(this.paramPanel, executeMethodFormNew.getMainPanel(), 0, 0, Sizes.ExecuteHistoryFormSize.PARAM_SIZE);
    }

    /**
     * 刷新参数面板
     *
     * @param executeResult
     */
    private void refreshResultPanel(ExecuteResult executeResult) {
        if (Objects.isNull(executeResult)) {
            return;
        }

        executeMethodResultForm = new ExecuteMethodResultForm(psiMethod, executeResult.getEtRsp());
        this.resultPanel.removeAll();
        this.resultPanel.setLayout(SwingUtils.createLayoutManager(1, 1));
        this.addCell(this.resultPanel, executeMethodResultForm.getMainPanel(), 0, 0, Sizes.ExecuteHistoryFormSize.RESULT_SIZE);
    }

    @Override
    public JComponent getMainPanel() {
        return this.mainPanel;
    }
}
